package avicit.bdp.lineage.druid.process.sqlselectquery;

import avicit.bdp.lineage.druid.model.ColumnNode;
import avicit.bdp.lineage.druid.model.TableNode;
import avicit.bdp.lineage.druid.model.TreeNode;
import avicit.bdp.lineage.druid.process.ProcessorRegister;
import avicit.bdp.lineage.druid.process.SqlExprContent;
import com.alibaba.druid.sql.ast.SQLAdhocTableSource;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.statement.SQLLateralViewTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUnionQueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLValuesTableSource;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>
 * SQLSelectQuery
 * </p>
 *
 */
public abstract class AbstractSQLSelectQueryProcessor implements SQLSelectQueryProcessor {


    @Override
    public void process(String dbType, AtomicInteger sequence, TreeNode<TableNode> parent,
                        SQLSelectQuery sqlSelectQuery) {

    }

    /**
     * SQLSelectStatement 考虑中
     * SQLCreateTableStatement 考虑中
     * SQLSubqueryTableSource V SQLObject Contain SQLSelect 时, 合并
     * SQLSubqueryTableSource 中的
     *
     * @param sqlObject sqlObject
     * @return alias
     */
    protected String getSubqueryTableSourceAlias(SQLObject sqlObject) {
        SQLObject parentObject = sqlObject.getParent().getParent();
        if (sqlObject.getParent() == null || parentObject == null) {
            return null;
        }
        if (parentObject instanceof SQLSubqueryTableSource) {
            SQLSubqueryTableSource tableSource = (SQLSubqueryTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLUnionQueryTableSource) {
            SQLUnionQueryTableSource tableSource = (SQLUnionQueryTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLJoinTableSource) {
            SQLJoinTableSource tableSource = (SQLJoinTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLExprTableSource) {
            SQLExprTableSource tableSource = (SQLExprTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLValuesTableSource) {
            SQLValuesTableSource tableSource = (SQLValuesTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLAdhocTableSource) {
            SQLAdhocTableSource tableSource = (SQLAdhocTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLLateralViewTableSource) {
            SQLLateralViewTableSource tableSource = (SQLLateralViewTableSource) parentObject;
            return tableSource.getAlias();
        } else if (parentObject instanceof SQLSelectStatement
                || parentObject instanceof SQLCreateTableStatement) {
            //throw new UnsupportedOperationException(parentObject.getClass().getName());
            return null;
        } else {
            return null;
        }
    }

    /**
     * 构建字段，带来源字段
     *
     * @param dbType        数据库类型
     * @param sqlSelectItem SQLSelectItem
     * @return ColumnNode
     */
    public ColumnNode convertSelectItem2Column(String dbType, SQLSelectItem sqlSelectItem) {
        //      1. 如果字段由多字段构成
        //        a. 别名不为空
        //   ​	设置别名为第一层字段，来源字段为列表
        //        b. 别名为空
        //   ​	    // todo，现在考虑为多字段必须写上别名
        //        暂时考虑不为空
        //      2. 如果字段由单字段构成
        //        a. 别名为空。
        //   ​	取出字段名，取出表名。
        //        b. 别名不为空。
        //      3. 考虑来源字段为文本｜int 值
        //         // todo 现在考虑为字段为文本｜ int值时过滤掉
        //   ​	设置别名为第一层字段，来源字段为列表
        SQLExpr sqlExpr = sqlSelectItem.getExpr();
        SqlExprContent sqlExprContent = SqlExprContent.of();
        ProcessorRegister.getSQLExprProcessor(sqlExpr.getClass()).process(dbType, sqlExpr, sqlExprContent);
        String alias = sqlSelectItem.getAlias();
        //如果select item没有列名别名，则以列为名称
        String columnName = null;
        if(StringUtils.isBlank(alias)){
            columnName = sqlExpr.toString();
        }
        if (sqlExprContent.isEmptyChildren()) {
            String name = sqlExprContent.getName();
            String ownerTable = sqlExprContent.getOwner();
            ColumnNode columnNode = ColumnNode.builder()
                    .name(name)
                    .tableName(ownerTable)
                    .build();
            if (!StringUtils.isEmpty(alias)) {
                columnNode.setAlias(alias);
            }
            return columnNode;
        }
        ColumnNode firstColumnNode = ColumnNode.builder().name(columnName).alias(alias).sourceColumns(new ArrayList<>()).build();

        List<SqlExprContent> allItems = sqlExprContent.getAllItems();
        List<ColumnNode> sourceColumnNodeList = new ArrayList<>();
        allItems.forEach(item -> sourceColumnNodeList
                .add(ColumnNode.builder().name(item.getName()).tableName(item.getOwner()).build()));
        firstColumnNode.getSourceColumns().addAll(sourceColumnNodeList);

        return firstColumnNode;
    }
}
